/**
 * Copyright (C) 2021-2022 maminjie <canpool@163.com>
 * SPDX-License-Identifier: LGPL-2.1
 * Powered by Qt-Advanced-Docking-System
**/

#pragma once

#include "dockfloatingbase.h"

#include <QRubberBand>

#ifdef Q_OS_LINUX
#include <QDockWidget>
using DockFloatingWidgetBase = QDockWidget;
#else
#include <QWidget>
using DockFloatingWidgetBase = QWidget;
#endif

QADS_BEGIN_NAMESPACE

class DockFloatingWidgetPrivate;
class DockManager;
class DockManagerPrivate;
class DockPannel;
class DockContainer;
class DockWidget;
class DockManager;
class DockTab;
class DockTabPrivate;
class DockTitleBar;
class DockTitleBarPrivate;
class DockFloatingWidgetTitleBar;
class DockStateReader;

/**
 * This implements a floating widget that is a dock container that accepts
 * docking of dock widgets like the main window and that can be docked into
 * another dock container.
 * Every floating window of the docking system is a DockFloatingWidget.
 */
class QADS_EXPORT DockFloatingWidget : public DockFloatingWidgetBase,
        public DockFloatingInterface
{
    Q_OBJECT
public:
    using Super = DockFloatingWidgetBase;

public:
    DockFloatingWidget(DockManager *dockManager);
    DockFloatingWidget(DockPannel *dockPannel);
    DockFloatingWidget(DockWidget *dockWidget);
    ~DockFloatingWidget() override;

    DockContainer *dockContainer() const;

    bool isClosable() const;

    bool hasTopLevelDockWidget() const;
    DockWidget *topLevelDockWidget() const;
    QList<DockWidget *> dockWidgets() const;

    void hideAndDeleteLater();

#ifdef Q_OS_LINUX
    void onMaximizeRequest();

    void showNormal(bool fixGeometry=false);
    void showMaximized();
    bool isMaximized() const;
    void show();

    bool hasNativeTitleBar();
#endif

protected:
    void startFloating(const QPoint &dragStartPos, const QSize &size,
                       DragState dragState, QWidget *mouseEventHandler) override;
    void moveFloating() override;

    void startDragging(const QPoint &dragStartPos, const QSize &size,  QWidget *mouseEventHandler)
    {
        startFloating(dragStartPos, size, DraggingFloatingWidget, mouseEventHandler);
    }
    void finishDragging() override;

    void initFloatingGeometry(const QPoint &dragStartPos, const QSize &size)
    {
        startFloating(dragStartPos, size, DraggingInactive, nullptr);
    }

    void updateWindowTitle();
    bool restoreState(DockStateReader &stream, bool testing);

protected:
    void changeEvent(QEvent *event) override;
    void closeEvent(QCloseEvent *event) override;
    void hideEvent(QHideEvent *event) override;
    void showEvent(QShowEvent *event) override;

#ifdef Q_OS_MACOS
    virtual bool event(QEvent *event) override;
    virtual void moveEvent(QMoveEvent *event) override;
#endif

#ifdef Q_OS_LINUX
    virtual void moveEvent(QMoveEvent *event) override;
    virtual void resizeEvent(QResizeEvent *event) override;
    virtual bool event(QEvent *e) override;
#endif

#ifdef Q_OS_WIN
    /**
     * Native event filter for handling WM_MOVING messages on Windows
     */
# if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
# else
    virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
#endif
#endif

private:
    void onDockPannelsAddedOrRemoved();
    void onDockPannelCurrentChanged(int Index);

private:
    DockFloatingWidgetPrivate *d;
    friend class DockFloatingWidgetPrivate;
    friend class DockManager;
    friend class DockManagerPrivate;
    friend class DockTabPrivate;
    friend class DockTab;
    friend class DockTitleBar;
    friend class DockTitleBarPrivate;
    friend class DockWidget;
    friend class DockPannel;
    friend class DockFloatingWidgetTitleBar;
}; // class DockFloatingWidget

QADS_END_NAMESPACE
